Plots
Let’s try to recreate the same plots Grecian, et al. (2022) did to compare the evolution of some behavioral parameters across time between nes and ses.
Max Depth
p1 <- plot_comp(data_comp[phase == "day", ], "maxdepth", nb_days = 300) +
labs(
x = "# days since departure",
y = "Maximum Depth (m)",
title = "Day"
) +
scale_y_continuous(limits = c(0, data_comp[, max(maxdepth)])) +
theme_jjo()
p2 <- plot_comp(data_comp[phase == "night", ], "maxdepth", nb_days = 300) +
labs(
x = "# days since departure",
y = "Maximum Depth (m)",
title = "Night"
) +
scale_y_continuous(limits = c(0, data_comp[, max(maxdepth)])) +
theme_jjo() +
theme(
axis.title.y = element_blank(),
axis.ticks.y = element_blank(),
axis.text.y = element_blank()
)
ggarrange(p1, p2, ncol = 2, common.legend = TRUE, legend = "bottom")
Dive Duration
p1 <- plot_comp(data_comp[phase == "day", ], "dduration", nb_days = 300) +
labs(
x = "# days since departure",
y = "Dive Duration (s)",
title = "Day"
) +
scale_y_continuous(limits = c(0, data_comp[, quantile(dduration,0.99)])) +
theme_jjo()
p2 <- plot_comp(data_comp[phase == "night", ], "dduration", nb_days = 200) +
labs(
x = "# days since departure",
y = "Dive Duration (s)",
title = "Night"
) +
scale_y_continuous(limits = c(0, data_comp[, quantile(dduration,0.99)])) +
theme_jjo() +
theme(
axis.title.y = element_blank(),
axis.ticks.y = element_blank(),
axis.text.y = element_blank()
)
ggarrange(p1, p2, ncol = 2, common.legend = TRUE, legend = "bottom")
“bADL”
# data nes
days_to_keep_nes = data_comp[sp=="nes",
.(nb_dives = .N),
by = .(.id, day_departure)] %>%
.[nb_dives >= 50,]
# keep only those days
data_nes_complete_day = merge(data_comp[sp == "nes",],
days_to_keep_nes,
by = c(".id", "day_departure"))
# data ses
days_to_keep_ses = data_comp[sp=="ses",
.(nb_dives = .N),
by = .(.id, day_departure)] %>%
.[nb_dives >= 8,]
# keep only those days
data_ses_complete_day = merge(data_comp[sp == "ses",],
days_to_keep_ses,
by = c(".id", "day_departure"))
# data plot
dataPlot = rbind(data_nes_complete_day[divetype=="1: foraging",
.(badl = quantile(dduration, 0.95)),
by = .(.id, day_departure, sp)],
data_ses_complete_day[divetype=="1: foraging",
.(badl = quantile(dduration, 0.95)),
by = .(.id, day_departure, sp)])
# comparative plot
plot_comp(dataPlot, "badl", nb_days = 300, alpha_point = .1) +
labs(
x = "# days since departure",
y = "bADL (s)",
title = "Day"
) +
scale_y_continuous(limits = c(0, dataPlot[, quantile(badl,0.99)])) +
theme_jjo()
Drift Rate
# calculate drift rate per day, id and sp
dataPlot = data_comp[divetype == "2: drift",
.(driftrate = quantile(driftrate, 0.5)),
by = .(day_departure, .id, sp)
]
# comparative plot
p1 = plot_comp(dataPlot, "driftrate", nb_days = 300, alpha_point = .1) +
labs(
x = "# days since departure",
y = "Drift Rate (m/s)",
title = "Day"
) +
theme_jjo() +
theme(legend.position = "bottom")
p2 = ggplot(dataPlot, aes(x = day_departure, y = driftrate, col = .id)) +
geom_point(show.legend = FALSE) +
facet_grid(sp~.) +
theme_jjo() +
theme(axis.title.y = element_blank())
ggarrange(p1, p2, ncol = 2)
It’s weird that there is still a bimodality in the maxdepth’s distribution for northern elephant seal, even after splitting day and night.
To investigate why is that, let’s try several representation of this data for the individual 2018070 (nes).
# let's pick an individual
data_test <- data_comp[.id == "ind_2018070", ]
# first we average `lightatsurf` by individuals, day since departure and hour
dataPlot <- data_test[, .(lightatsurf = median(lightatsurf, na.rm = T),
phase = first(phase)),
by = .(.id,
day_departure,
date = as.Date(date),
hour)]
# then we choose the variable to represent
i <- "maxdepth"
ggplot(data = melt(data_test[, .(.id, date, get(i), phase)],
id.vars = c(".id",
"date",
"phase")),
aes(x = as.Date(date),
y = value,
col = phase)) +
geom_point(alpha = 1 / 10,
size = .5) +
facet_wrap(. ~ .id, scales = "free") +
scale_x_date(date_labels = "%m/%Y") +
labs(x = "Date", y = i) +
theme_jjo() +
theme(axis.text.x = element_text(angle = 45, hjust = 1),
legend.position = "bottom") +
guides(colour = guide_legend(override.aes = list(size = 7,
alpha = 1)))
For this individual we can see that there are still a lot of shallow dives during the day. I first thought it was because this individual would probably have started reaching shallow water earlier in the day, at dusk, rather than waiting for complete darkness. To test this hypothesis, I tried to visualize the maxdepth over an entire day throughout the trip.
# this is art!
htmltools::tagList(list(
plot_ly() %>%
add_trace(
data = data_test,
x = ~hour,
y = ~day_departure,
z = ~ -maxdepth,
marker = list(
size = 1,
opacity = 0.5
),
mode = "markers",
type = "scatter3d",
text = ~divenumber
) %>%
add_trace(
x = ~hour,
y = ~day_departure,
z = ~ (lightatsurf / 200) * 20,
intensity = ~ lightatsurf / 200,
data = dataPlot,
type = "mesh3d",
showlegend = FALSE
) %>%
layout(
scene = list(
zaxis = list(title = "Maximum depth (m)"),
yaxis = list(title = "# days since departure"),
xaxis = list(title = "Hour")
),
legend = list(itemsizing = "constant")
)))
We can see the bimodality of maxdepth within a day is not related to the time of the day, since swallow and deep dives might both occurred at the same time in the day. Let’s see what happen if we color dives with divetype.
# this is art!
htmltools::tagList(list(
plot_ly() %>%
add_trace(
data = data_test,
x = ~hour,
y = ~day_departure,
z = ~ -maxdepth,
color = ~divetype,
marker = list(
size = 1,
opacity = 0.5
),
mode = "markers",
type = "scatter3d",
text = ~divenumber
) %>%
add_trace(
x = ~hour,
y = ~day_departure,
z = ~ (lightatsurf / 200) * 20,
intensity = ~ lightatsurf / 200,
data = dataPlot,
type = "mesh3d",
showlegend = FALSE
) %>%
layout(
scene = list(
zaxis = list(title = "Maximum depth (m)"),
yaxis = list(title = "# days since departure"),
xaxis = list(title = "Hour")
),
legend = list(itemsizing = "constant")
)
))
Well it seems that the bimodality observed in the distribution of maxdepth is mostly explained by divetype, with transit dives occurring at deeper dives that foraging and drift dives (at least for northern elephant seal). We can actually look at the same result with a simple 2D plot:
ggplot(
data = melt(data_test[, .(.id, date, get(i), divetype)],
id.vars = c(
".id",
"date",
"divetype"
)
),
aes(
x = as.Date(date),
y = value,
col = divetype
)
) +
geom_point(
alpha = 1 / 10,
size = .5
) +
facet_wrap(. ~ .id, scales = "free") +
scale_x_date(date_labels = "%m/%Y") +
labs(x = "Date", y = i) +
theme_jjo() +
theme(
axis.text.x = element_text(angle = 45, hjust = 1),
legend.position = "bottom"
) +
guides(colour = guide_legend(override.aes = list(
size = 7,
alpha = 1
)))
And in bonus, we can add the bathymetry to the 3D plot.
htmltools::tagList(list(
plot_ly() %>%
add_trace(
data = data_test,
x = ~hour,
y = ~day_departure,
z = ~ -maxdepth,
color = ~divetype,
marker = list(
size = 1,
opacity = 0.5
),
mode = "markers",
type = "scatter3d",
text = ~divenumber
) %>%
add_trace(
x = ~hour,
y = ~day_departure,
z = ~ (lightatsurf / 200) * 20,
intensity = ~ lightatsurf / 200,
data = dataPlot,
type = "mesh3d",
showlegend = FALSE
) %>%
add_trace(
x = ~hour,
y = ~day_departure,
z = ~bathy,
data = data_test,
type = "mesh3d"
) %>%
layout(
scene = list(
zaxis = list(title = "Maximum depth (m)"),
yaxis = list(title = "# days since departure"),
xaxis = list(title = "Hour")
),
legend = list(itemsizing = "constant")
)))
What about Southern Elephant Seals ?!?
To investigate why is that, let’s try several representation of this data for the individual 140059 (ses).
# let's pick an individual
data_test <- data_comp[.id == "ind_140059",]
# first we average `lightatsurf` by individuals, day since departure and hour
dataPlot <- data_test[, .(lightatsurf = median(lightatsurf, na.rm = T),
phase = first(phase)),
by = .(.id,
day_departure,
date = as.Date(date),
hour)]
# then we choose the variable to represent
i <- "maxdepth"
ggplot(data = melt(data_test[, .(.id, date, get(i), phase)],
id.vars = c(".id",
"date",
"phase")),
aes(x = as.Date(date),
y = value,
col = phase)) +
geom_point(alpha = 1 / 5,
size = .5) +
facet_wrap(. ~ .id, scales = "free") +
scale_x_date(date_labels = "%m/%Y") +
labs(x = "Date", y = i) +
theme_jjo() +
theme(axis.text.x = element_text(angle = 45, hjust = 1),
legend.position = "bottom") +
guides(colour = guide_legend(override.aes = list(size = 7,
alpha = 1)))
For this individual we can see that until the half of its trip, there is no distinction between day and night in terms of maxdepth. But After, he starts to dive deeper during the day, and shallower during the night. Contrary to the previous nes individual, there seems to be a clear pattern. Let’s look at the graph in 3D:
# this is art!
htmltools::tagList(list(
plot_ly() %>%
add_trace(
data = data_test,
x = ~hour,
y = ~day_departure,
z = ~ -maxdepth,
marker = list(
size = 1,
opacity = 0.8
),
mode = "markers",
type = "scatter3d",
text = ~divenumber
) %>%
add_trace(
x = ~hour,
y = ~day_departure,
z = ~ (hour * 0.1) + 20,
intensity = ~phase_bool,
data = dataPlot[][, phase_bool := fifelse(phase == "night", 0, 1)][],
type = "mesh3d",
showlegend = FALSE
) %>%
layout(
scene = list(
zaxis = list(title = "Maximum depth (m)"),
yaxis = list(title = "# days since departure"),
xaxis = list(title = "Hour")
),
legend = list(itemsizing = "constant")
)))
We can clearly see that pass half of its trip, this individual starts to dive deeper during the day. Let’s see what happen if we color dives with divetype.
# this is art!
htmltools::tagList(list(
plot_ly() %>%
add_trace(
data = data_test,
x = ~hour,
y = ~day_departure,
z = ~ -maxdepth,
color = ~divetype,
marker = list(
size = 1,
opacity = 0.8
),
mode = "markers",
type = "scatter3d",
text = ~divenumber
) %>%
add_trace(
x = ~hour,
y = ~day_departure,
z = ~ (hour * 0.1) + 20,
intensity = ~phase_bool,
data = dataPlot[][, phase_bool := fifelse(phase == "night", 0, 1)][],
type = "mesh3d",
showlegend = FALSE
) %>%
layout(
scene = list(
zaxis = list(title = "Maximum depth (m)"),
yaxis = list(title = "# days since departure"),
xaxis = list(title = "Hour")
),
legend = list(itemsizing = "constant")
)
))
It’s hard to tell something, most of the dives seem to be foraging dives, and follow the pattern identified previously. The other interesting results would be a lot of benthic dives at the beginning, and drift dives occurring mostly during the day. Let’s look at a simple 2D plot:
ggplot(
data = melt(data_test[, .(.id, date, get(i), divetype)],
id.vars = c(
".id",
"date",
"divetype"
)
),
aes(
x = as.Date(date),
y = value,
col = divetype
)
) +
geom_point(
alpha = 1 / 5,
size = .5
) +
facet_wrap(. ~ .id, scales = "free") +
scale_x_date(date_labels = "%m/%Y") +
labs(x = "Date", y = i) +
theme_jjo() +
theme(
axis.text.x = element_text(angle = 45, hjust = 1),
legend.position = "bottom"
) +
guides(colour = guide_legend(override.aes = list(
size = 7,
alpha = 1
)))
And in bonus, we can add the bathymetry to the 3D plot.
htmltools::tagList(list(plot_ly() %>%
add_trace(
data = data_test,
x = ~hour,
y = ~day_departure,
z = ~ -maxdepth,
color = ~divetype,
marker = list(
size = 1,
opacity = 0.8
),
mode = "markers",
type = "scatter3d",
text = ~divenumber
) %>%
add_trace(
x = ~hour,
y = ~day_departure,
z = ~ (lightatsurf / 200) * 20,
intensity = ~ lightatsurf / 200,
data = dataPlot,
type = "mesh3d",
showlegend = FALSE
) %>%
add_trace(
x = ~hour,
y = ~day_departure,
z = ~bathy,
data = data_test,
type = "mesh3d"
) %>%
layout(
scene = list(
zaxis = list(title = "Maximum depth (m)"),
yaxis = list(title = "# days since departure"),
xaxis = list(title = "Hour")
),
legend = list(itemsizing = "constant")
)))
LS0tCnRpdGxlOiAiRGF0YSBDb21wYXJpc29uIC0gTkVTIHZzIFNFUyAoV0lQKSIKYXV0aG9yOiAiSm9mZnJleSBKT1VNQUEiCmRhdGU6ICJgciBpbnZpc2libGUoU3lzLnNldGxvY2FsZShsb2NhbGUgPSAnQycpKTsgZm9ybWF0KFN5cy5EYXRlKCksIGZvcm1hdCA9ICclQiAlZCwgJVknKWAiCm91dHB1dDoKICBib29rZG93bjo6aHRtbF9kb2N1bWVudDI6CiAgICBjc3M6IGNvc21vX2N1c3RvbS5jc3MKICAgIG51bWJlcl9zZWN0aW9uczogeWVzCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cKICAgIGRmX3ByaW50OiBkZWZhdWx0CiAgICBmaWdfY2FwdGlvbjogeWVzCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMKICAgIHRvYzogeWVzCiAgICB0b2NfZmxvYXQ6CiAgICAgIGNvbGxhcHNlZDogeWVzCiAgICAgIHNtb290aF9zY3JvbGw6IG5vCnZpZ25ldHRlOiA+CiAgJVxWaWduZXR0ZUluZGV4RW50cnl7RGF0YSBDb21wYXJpc29uIC0gTkVTIHZzIFNFUyAoV0lQKX0KICAlXFZpZ25ldHRlRW5naW5le2tuaXRyOjpybWFya2Rvd259CiAgJVxWaWduZXR0ZUVuY29kaW5ne1VURi04fQotLS0KCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0KIyBjb21tYW5kIHRvIGJ1aWxkIHBhY2thZ2Ugd2l0aG91dCBnZXR0aW5nIHZpZ25ldHRlIGVycm9yCiMgaHR0cHM6Ly9naXRodWIuY29tL3JzdHVkaW8vcmVudi9pc3N1ZXMvODMzCiMgZGV2dG9vbHM6OmNoZWNrKGJ1aWxkX2FyZ3M9YygiLS1uby1idWlsZC12aWduZXR0ZXMiKSkKCiMgIyByZWR1Y2UgcG5nIHNpemUKIyBrbml0cjo6a25pdF9ob29rcyRzZXQob3B0aXBuZyA9IGtuaXRyOjpob29rX29wdGlwbmcpCiMga25pdHI6OmtuaXRfaG9va3Mkc2V0KHBuZ3F1YW50ID0ga25pdHI6Omhvb2tfcG5ncXVhbnQpCgojIGdsb2JhbCBvcHRpb24gcmVsYXRpdmUgdG8gcm1hcmtkb3duCmtuaXRyOjpvcHRzX2NodW5rJHNldCgKICBlY2hvID0gVFJVRSwKICBmaWcuYWxpZ24gPSAiY2VudGVyIiwKICBvdXQud2lkdGggPSAiMTAwJSIsCiAgbWVzc2FnZSA9IEZBTFNFLAogIHdhcm5pbmcgPSBGQUxTRSwKICBjYWNoZS5sYXp5ID0gRkFMU0UsCiAgb3B0aXBuZyA9ICItbzcgLXF1aWV0IiwKICBwbmdxdWFudCA9ICItLXNwZWVkPTEiCikKCiMgbGlicmFyeQpsaWJyYXJ5KGRhdGEudGFibGUpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShrYWJsZUV4dHJhKQpsaWJyYXJ5KGNvcnJwbG90KQpsaWJyYXJ5KG1hZ3JpdHRyKQpsaWJyYXJ5KGdncHVicikKbGlicmFyeShwbG90bHkpCgojIHJlbW92ZSBzb21lIHdhcm5pbmdzCnN1cHByZXNzV2FybmluZ3MobGlicmFyeShnZ3Bsb3QyKSkKCiMgZGVmaW5lIG15IG93biB0YWJsZSBmb3JtYXQ6IGh0dHBzOi8vZ2l0aHViLmNvbS9oYW96aHUyMzMva2FibGVFeHRyYS9pc3N1ZXMvMzc0CnNhYmxlIDwtIGZ1bmN0aW9uKHgsIGVzY2FwZSA9IFQsIC4uLikgewogIGtuaXRyOjprYWJsZSh4LCBlc2NhcGUgPSBlc2NhcGUsIC4uLikgJT4lCiAgICBrYWJsZV9zdHlsaW5nKAogICAgICBib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAicmVzcG9uc2l2ZSIpLAogICAgICBmdWxsX3dpZHRoID0gRgogICAgKQp9CmBgYAoKIyMgSW1wb3J0IERhdGEKCmBgYHtyfQojIGxvYWQgd2VhbGluZ05FUyBwYWNrYWdlCmxpYnJhcnkod2VhbmxpbmdORVMpCgojIGxvYWQgZGF0YXNldApkYXRhKCJkYXRhX25lcyIpCmRhdGEoImRhdGFfc2VzIikKCiMgbWVyZ2UgaW50byBvbmUgZGF0YXNldApkYXRhX2NvbXAgPC0gcmJpbmQoCiAgcmJpbmRsaXN0KGRhdGFfbmVzJHllYXJfMjAxOCkgJT4lCiAgICAuWywgc3AgOj0gIm5lcyJdLAogIHJiaW5kbGlzdChkYXRhX3NlcyR5ZWFyXzIwMTQpICU+JQogICAgLlssIHNwIDo9ICJzZXMiXSwKICB1c2UubmFtZXMgPSBULAogIGZpbGwgPSBUCikKYGBgCgojIyBQbG90cyB7LnRhYnNldCAudGFic2V0LWZhZGUgLnRhYnNldC1waWxsc30KCkxldCdzIHRyeSB0byByZWNyZWF0ZSB0aGUgc2FtZSBwbG90cyBbR3JlY2lhbiwgKmV0IGFsLiogKDIwMjIpXShodHRwczovL2RvaS5vcmcvMTAuMTA5OC9yc29zLjIxMTA0MikgZGlkIHRvIGNvbXBhcmUgdGhlIGV2b2x1dGlvbiBvZiBzb21lIGJlaGF2aW9yYWwgcGFyYW1ldGVycyBhY3Jvc3MgdGltZSBiZXR3ZWVuIG5lcyBhbmQgc2VzLgoKIyMjIE1heCBEZXB0aAoKYGBge3IgZmlnLmNhcD0iRXN0aW1hdGVkIHRlbXBvcmFsIGNoYW5nZXMgaW4gbWF4aW11bSBkZXB0aCAobSkifQpwMSA8LSBwbG90X2NvbXAoZGF0YV9jb21wW3BoYXNlID09ICJkYXkiLCBdLCAibWF4ZGVwdGgiLCBuYl9kYXlzID0gMzAwKSArCiAgbGFicygKICAgIHggPSAiIyBkYXlzIHNpbmNlIGRlcGFydHVyZSIsCiAgICB5ID0gIk1heGltdW0gRGVwdGggKG0pIiwKICAgIHRpdGxlID0gIkRheSIKICApICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCBkYXRhX2NvbXBbLCBtYXgobWF4ZGVwdGgpXSkpICsKICB0aGVtZV9qam8oKQpwMiA8LSBwbG90X2NvbXAoZGF0YV9jb21wW3BoYXNlID09ICJuaWdodCIsIF0sICJtYXhkZXB0aCIsIG5iX2RheXMgPSAzMDApICsKICBsYWJzKAogICAgeCA9ICIjIGRheXMgc2luY2UgZGVwYXJ0dXJlIiwKICAgIHkgPSAiTWF4aW11bSBEZXB0aCAobSkiLAogICAgdGl0bGUgPSAiTmlnaHQiCiAgKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgZGF0YV9jb21wWywgbWF4KG1heGRlcHRoKV0pKSArCiAgdGhlbWVfampvKCkgKwogIHRoZW1lKAogICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy50aWNrcy55ID0gZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X2JsYW5rKCkKICApCmdnYXJyYW5nZShwMSwgcDIsIG5jb2wgPSAyLCBjb21tb24ubGVnZW5kID0gVFJVRSwgbGVnZW5kID0gImJvdHRvbSIpCmBgYAoKIyMjIERpdmUgRHVyYXRpb24KCmBgYHtyIGZpZy5jYXA9IkVzdGltYXRlZCB0ZW1wb3JhbCBjaGFuZ2VzIGluIGRpdmUgZHVyYXRpb24gKHMpIn0KcDEgPC0gcGxvdF9jb21wKGRhdGFfY29tcFtwaGFzZSA9PSAiZGF5IiwgXSwgImRkdXJhdGlvbiIsIG5iX2RheXMgPSAzMDApICsKICBsYWJzKAogICAgeCA9ICIjIGRheXMgc2luY2UgZGVwYXJ0dXJlIiwKICAgIHkgPSAiRGl2ZSBEdXJhdGlvbiAocykiLAogICAgdGl0bGUgPSAiRGF5IgogICkgKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIGRhdGFfY29tcFssIHF1YW50aWxlKGRkdXJhdGlvbiwwLjk5KV0pKSArCiAgdGhlbWVfampvKCkKcDIgPC0gcGxvdF9jb21wKGRhdGFfY29tcFtwaGFzZSA9PSAibmlnaHQiLCBdLCAiZGR1cmF0aW9uIiwgbmJfZGF5cyA9IDIwMCkgKwogIGxhYnMoCiAgICB4ID0gIiMgZGF5cyBzaW5jZSBkZXBhcnR1cmUiLAogICAgeSA9ICJEaXZlIER1cmF0aW9uIChzKSIsCiAgICB0aXRsZSA9ICJOaWdodCIKICApICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCBkYXRhX2NvbXBbLCBxdWFudGlsZShkZHVyYXRpb24sMC45OSldKSkgKwogIHRoZW1lX2pqbygpICsKICB0aGVtZSgKICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGF4aXMudGlja3MueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF9ibGFuaygpCiAgKQpnZ2FycmFuZ2UocDEsIHAyLCBuY29sID0gMiwgY29tbW9uLmxlZ2VuZCA9IFRSVUUsIGxlZ2VuZCA9ICJib3R0b20iKQpgYGAKCiMjIyAiYkFETCIKCmBgYHtyIGZpZy5jYXA9IkVzdGltYXRlZCB0ZW1wb3JhbCBjaGFuZ2VzIGluIGJBREwgKHMpIn0KIyBkYXRhIG5lcwpkYXlzX3RvX2tlZXBfbmVzID0gZGF0YV9jb21wW3NwPT0ibmVzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuKG5iX2RpdmVzID0gLk4pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gLiguaWQsIGRheV9kZXBhcnR1cmUpXSAlPiUKICAuW25iX2RpdmVzID49IDUwLF0KIyBrZWVwIG9ubHkgdGhvc2UgZGF5cwpkYXRhX25lc19jb21wbGV0ZV9kYXkgPSBtZXJnZShkYXRhX2NvbXBbc3AgPT0gIm5lcyIsXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXlzX3RvX2tlZXBfbmVzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gYygiLmlkIiwgImRheV9kZXBhcnR1cmUiKSkKIyBkYXRhIHNlcwpkYXlzX3RvX2tlZXBfc2VzID0gZGF0YV9jb21wW3NwPT0ic2VzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuKG5iX2RpdmVzID0gLk4pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gLiguaWQsIGRheV9kZXBhcnR1cmUpXSAlPiUKICAuW25iX2RpdmVzID49IDgsXQojIGtlZXAgb25seSB0aG9zZSBkYXlzCmRhdGFfc2VzX2NvbXBsZXRlX2RheSA9IG1lcmdlKGRhdGFfY29tcFtzcCA9PSAic2VzIixdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRheXNfdG9fa2VlcF9zZXMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnkgPSBjKCIuaWQiLCAiZGF5X2RlcGFydHVyZSIpKQojIGRhdGEgcGxvdApkYXRhUGxvdCA9IHJiaW5kKGRhdGFfbmVzX2NvbXBsZXRlX2RheVtkaXZldHlwZT09IjE6IGZvcmFnaW5nIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuKGJhZGwgPSBxdWFudGlsZShkZHVyYXRpb24sIDAuOTUpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieSA9IC4oLmlkLCBkYXlfZGVwYXJ0dXJlLCBzcCldLAogICAgICAgICAgICAgICAgIGRhdGFfc2VzX2NvbXBsZXRlX2RheVtkaXZldHlwZT09IjE6IGZvcmFnaW5nIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuKGJhZGwgPSBxdWFudGlsZShkZHVyYXRpb24sIDAuOTUpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieSA9IC4oLmlkLCBkYXlfZGVwYXJ0dXJlLCBzcCldKQoKIyBjb21wYXJhdGl2ZSBwbG90CnBsb3RfY29tcChkYXRhUGxvdCwgImJhZGwiLCBuYl9kYXlzID0gMzAwLCBhbHBoYV9wb2ludCA9IC4xKSArCiAgbGFicygKICAgIHggPSAiIyBkYXlzIHNpbmNlIGRlcGFydHVyZSIsCiAgICB5ID0gImJBREwgKHMpIiwKICAgIHRpdGxlID0gIkRheSIKICApICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCBkYXRhUGxvdFssIHF1YW50aWxlKGJhZGwsMC45OSldKSkgKwogIHRoZW1lX2pqbygpCmBgYAoKIyMjIERyaWZ0IFJhdGUKCmBgYHtyIGZpZy5jYXA9IkVzdGltYXRlZCB0ZW1wb3JhbCBjaGFuZ2VzIGluIGRyaWZ0IHJhdGUgKG0vcykifQojIGNhbGN1bGF0ZSBkcmlmdCByYXRlIHBlciBkYXksIGlkIGFuZCBzcApkYXRhUGxvdCA9IGRhdGFfY29tcFtkaXZldHlwZSA9PSAiMjogZHJpZnQiLAogIC4oZHJpZnRyYXRlID0gcXVhbnRpbGUoZHJpZnRyYXRlLCAwLjUpKSwKICBieSA9IC4oZGF5X2RlcGFydHVyZSwgLmlkLCBzcCkKXQoKIyBjb21wYXJhdGl2ZSBwbG90CnAxID0gcGxvdF9jb21wKGRhdGFQbG90LCAiZHJpZnRyYXRlIiwgbmJfZGF5cyA9IDMwMCwgYWxwaGFfcG9pbnQgPSAuMSkgKwogIGxhYnMoCiAgICB4ID0gIiMgZGF5cyBzaW5jZSBkZXBhcnR1cmUiLAogICAgeSA9ICJEcmlmdCBSYXRlIChtL3MpIiwKICAgIHRpdGxlID0gIkRheSIKICApICsKICB0aGVtZV9qam8oKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpCnAyID0gZ2dwbG90KGRhdGFQbG90LCBhZXMoeCA9IGRheV9kZXBhcnR1cmUsIHkgPSBkcmlmdHJhdGUsIGNvbCA9IC5pZCkpICsKICBnZW9tX3BvaW50KHNob3cubGVnZW5kID0gRkFMU0UpICsKICBmYWNldF9ncmlkKHNwfi4pICsKICB0aGVtZV9qam8oKSArCiAgdGhlbWUoYXhpcy50aXRsZS55ID0gZWxlbWVudF9ibGFuaygpKQpnZ2FycmFuZ2UocDEsIHAyLCBuY29sID0gMikKYGBgCgojIyB7LnVubGlzdGVkIC51bm51bWJlcmVkfQoKPiBJdCdzIHdlaXJkIHRoYXQgdGhlcmUgaXMgc3RpbGwgYSBiaW1vZGFsaXR5IGluIHRoZSBgbWF4ZGVwdGhgJ3MgZGlzdHJpYnV0aW9uIGZvciBub3J0aGVybiBlbGVwaGFudCBzZWFsLCBldmVuIGFmdGVyIHNwbGl0dGluZyBgZGF5YCBhbmQgYG5pZ2h0YC4KClRvIGludmVzdGlnYXRlIHdoeSBpcyB0aGF0LCBsZXQncyB0cnkgc2V2ZXJhbCByZXByZXNlbnRhdGlvbiBvZiB0aGlzIGRhdGEgZm9yIHRoZSBpbmRpdmlkdWFsIGAyMDE4MDcwYCAobmVzKS4KCmBgYHtyIGZpZy5jYXA9IkV2b2x1dGlvbiBvZiB0aGUgbWF4aW11bSBkZXB0aCByZWFjaGVkIGFjcm9zcyB0aW1lIGZvciB0aGUgaW5kaXZpZHVhbCAyMDE4MDcwIn0KIyBsZXQncyBwaWNrIGFuIGluZGl2aWR1YWwKZGF0YV90ZXN0IDwtIGRhdGFfY29tcFsuaWQgPT0gImluZF8yMDE4MDcwIiwgXQoKIyBmaXJzdCB3ZSBhdmVyYWdlIGBsaWdodGF0c3VyZmAgYnkgaW5kaXZpZHVhbHMsIGRheSBzaW5jZSBkZXBhcnR1cmUgYW5kIGhvdXIKZGF0YVBsb3QgPC0gZGF0YV90ZXN0WywgLihsaWdodGF0c3VyZiA9IG1lZGlhbihsaWdodGF0c3VyZiwgbmEucm0gPSBUKSwKICAgICAgICAgICAgICAgICAgICAgICAgICBwaGFzZSA9IGZpcnN0KHBoYXNlKSksCiAgICAgICAgICAgICAgICAgICAgICBieSA9IC4oLmlkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRheV9kZXBhcnR1cmUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0ZSA9IGFzLkRhdGUoZGF0ZSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaG91cildCgojIHRoZW4gd2UgY2hvb3NlIHRoZSB2YXJpYWJsZSB0byByZXByZXNlbnQKaSA8LSAibWF4ZGVwdGgiCmdncGxvdChkYXRhID0gbWVsdChkYXRhX3Rlc3RbLCAuKC5pZCwgZGF0ZSwgZ2V0KGkpLCBwaGFzZSldLAogICAgICAgICAgICAgICAgICAgaWQudmFycyA9IGMoIi5pZCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZGF0ZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAicGhhc2UiKSksCiAgICAgICBhZXMoeCA9IGFzLkRhdGUoZGF0ZSksCiAgICAgICAgICAgeSA9IHZhbHVlLAogICAgICAgICAgIGNvbCA9IHBoYXNlKSkgKwogIGdlb21fcG9pbnQoYWxwaGEgPSAxIC8gMTAsCiAgICAgICAgICAgICBzaXplID0gLjUpICsKICBmYWNldF93cmFwKC4gfiAuaWQsIHNjYWxlcyA9ICJmcmVlIikgKwogIHNjYWxlX3hfZGF0ZShkYXRlX2xhYmVscyA9ICIlbS8lWSIpICsKICBsYWJzKHggPSAiRGF0ZSIsIHkgPSBpKSArCiAgdGhlbWVfampvKCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpICsKICBndWlkZXMoY29sb3VyID0gZ3VpZGVfbGVnZW5kKG92ZXJyaWRlLmFlcyA9IGxpc3Qoc2l6ZSA9IDcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFscGhhID0gMSkpKQpgYGAKCkZvciB0aGlzIGluZGl2aWR1YWwgd2UgY2FuIHNlZSB0aGF0IHRoZXJlIGFyZSBzdGlsbCBhIGxvdCBvZiBzaGFsbG93IGRpdmVzIGR1cmluZyB0aGUgZGF5LiBJIGZpcnN0IHRob3VnaHQgaXQgd2FzIGJlY2F1c2UgdGhpcyBpbmRpdmlkdWFsIHdvdWxkIHByb2JhYmx5IGhhdmUgc3RhcnRlZCByZWFjaGluZyBzaGFsbG93IHdhdGVyIGVhcmxpZXIgaW4gdGhlIGRheSwgYXQgZHVzaywgcmF0aGVyIHRoYW4gd2FpdGluZyBmb3IgY29tcGxldGUgZGFya25lc3MuIFRvIHRlc3QgdGhpcyBoeXBvdGhlc2lzLCBJIHRyaWVkIHRvIHZpc3VhbGl6ZSB0aGUgYG1heGRlcHRoYCBvdmVyIGFuIGVudGlyZSBkYXkgdGhyb3VnaG91dCB0aGUgdHJpcC4gCgpgYGB7ciBmaWcuY2FwPSJNYXhpbXVtIGRlcHRoIGluIGZ1bmN0aW9uIG9mIHRoZSBudW1iZXIgb2YgZGF5cyBzaW5jZSBkZXBhcnR1cmUgYW5kIHRoZSBob3VyIG9mIHRoZSBkYXkgZm9yIGluZF8yMDE4MDcwIChuZXMpLiBUaGUgMi1EIHBsYW5lIGFsbG93IHRvIGlkZW50aWZ5IGRheSBhbmQgbmlnaHQgYmFzZWQgb24gbGlnaHQgbGV2ZWwifQojIHRoaXMgaXMgYXJ0IQpodG1sdG9vbHM6OnRhZ0xpc3QobGlzdCgKcGxvdF9seSgpICU+JQogIGFkZF90cmFjZSgKICAgIGRhdGEgPSBkYXRhX3Rlc3QsCiAgICB4ID0gfmhvdXIsCiAgICB5ID0gfmRheV9kZXBhcnR1cmUsCiAgICB6ID0gfiAtbWF4ZGVwdGgsCiAgICBtYXJrZXIgPSBsaXN0KAogICAgICBzaXplID0gMSwKICAgICAgb3BhY2l0eSA9IDAuNQogICAgKSwKICAgIG1vZGUgPSAibWFya2VycyIsCiAgICB0eXBlID0gInNjYXR0ZXIzZCIsCiAgICB0ZXh0ID0gfmRpdmVudW1iZXIKICApICU+JQogIGFkZF90cmFjZSgKICAgIHggPSB+aG91ciwKICAgIHkgPSB+ZGF5X2RlcGFydHVyZSwKICAgIHogPSB+IChsaWdodGF0c3VyZiAvIDIwMCkgKiAyMCwKICAgIGludGVuc2l0eSA9IH4gbGlnaHRhdHN1cmYgLyAyMDAsCiAgICBkYXRhID0gZGF0YVBsb3QsCiAgICB0eXBlID0gIm1lc2gzZCIsCiAgICBzaG93bGVnZW5kID0gRkFMU0UKICApICU+JQogIGxheW91dCgKICAgIHNjZW5lID0gbGlzdCgKICAgICAgemF4aXMgPSBsaXN0KHRpdGxlID0gIk1heGltdW0gZGVwdGggKG0pIiksCiAgICAgIHlheGlzID0gbGlzdCh0aXRsZSA9ICIjIGRheXMgc2luY2UgZGVwYXJ0dXJlIiksCiAgICAgIHhheGlzID0gbGlzdCh0aXRsZSA9ICJIb3VyIikKICAgICksCiAgICBsZWdlbmQgPSBsaXN0KGl0ZW1zaXppbmcgPSAiY29uc3RhbnQiKQogICkpKQpgYGAKCldlIGNhbiBzZWUgdGhlIGJpbW9kYWxpdHkgb2YgYG1heGRlcHRoYCB3aXRoaW4gYSBkYXkgaXMgbm90IHJlbGF0ZWQgdG8gdGhlIHRpbWUgb2YgdGhlIGRheSwgc2luY2Ugc3dhbGxvdyBhbmQgZGVlcCBkaXZlcyBtaWdodCBib3RoIG9jY3VycmVkIGF0IHRoZSBzYW1lIHRpbWUgaW4gdGhlIGRheS4gTGV0J3Mgc2VlIHdoYXQgaGFwcGVuIGlmIHdlIGNvbG9yIGRpdmVzIHdpdGggYGRpdmV0eXBlYC4KCmBgYHtyIGZpZy5jYXA9IlNhbWUgZ3JhcGggYnV0IHdpdGggYG1heGRlcHRoYCBjb2xvcmVkIGJ5IGBkaXZldHlwZWAifQojIHRoaXMgaXMgYXJ0IQpodG1sdG9vbHM6OnRhZ0xpc3QobGlzdCgKICBwbG90X2x5KCkgJT4lCiAgYWRkX3RyYWNlKAogICAgZGF0YSA9IGRhdGFfdGVzdCwKICAgIHggPSB+aG91ciwKICAgIHkgPSB+ZGF5X2RlcGFydHVyZSwKICAgIHogPSB+IC1tYXhkZXB0aCwKICAgIGNvbG9yID0gfmRpdmV0eXBlLAogICAgbWFya2VyID0gbGlzdCgKICAgICAgc2l6ZSA9IDEsCiAgICAgIG9wYWNpdHkgPSAwLjUKICAgICksCiAgICBtb2RlID0gIm1hcmtlcnMiLAogICAgdHlwZSA9ICJzY2F0dGVyM2QiLAogICAgdGV4dCA9IH5kaXZlbnVtYmVyCiAgKSAlPiUKICBhZGRfdHJhY2UoCiAgICB4ID0gfmhvdXIsCiAgICB5ID0gfmRheV9kZXBhcnR1cmUsCiAgICB6ID0gfiAobGlnaHRhdHN1cmYgLyAyMDApICogMjAsCiAgICBpbnRlbnNpdHkgPSB+IGxpZ2h0YXRzdXJmIC8gMjAwLAogICAgZGF0YSA9IGRhdGFQbG90LAogICAgdHlwZSA9ICJtZXNoM2QiLAogICAgc2hvd2xlZ2VuZCA9IEZBTFNFCiAgKSAlPiUKICBsYXlvdXQoCiAgICBzY2VuZSA9IGxpc3QoCiAgICAgIHpheGlzID0gbGlzdCh0aXRsZSA9ICJNYXhpbXVtIGRlcHRoIChtKSIpLAogICAgICB5YXhpcyA9IGxpc3QodGl0bGUgPSAiIyBkYXlzIHNpbmNlIGRlcGFydHVyZSIpLAogICAgICB4YXhpcyA9IGxpc3QodGl0bGUgPSAiSG91ciIpCiAgICApLAogICAgbGVnZW5kID0gbGlzdChpdGVtc2l6aW5nID0gImNvbnN0YW50IikKICApCikpCmBgYAoKV2VsbCBpdCBzZWVtcyB0aGF0IHRoZSBiaW1vZGFsaXR5IG9ic2VydmVkIGluIHRoZSBkaXN0cmlidXRpb24gb2YgYG1heGRlcHRoYCBpcyBtb3N0bHkgZXhwbGFpbmVkIGJ5IGBkaXZldHlwZWAsIHdpdGggKnRyYW5zaXQqIGRpdmVzIG9jY3VycmluZyBhdCBkZWVwZXIgZGl2ZXMgdGhhdCAqZm9yYWdpbmcqIGFuZCAqZHJpZnQqIGRpdmVzIChhdCBsZWFzdCBmb3Igbm9ydGhlcm4gZWxlcGhhbnQgc2VhbCkuIFdlIGNhbiBhY3R1YWxseSBsb29rIGF0IHRoZSBzYW1lIHJlc3VsdCB3aXRoIGEgc2ltcGxlIDJEIHBsb3Q6CgpgYGB7ciBmaWcuY2FwPSJLaW5kIG9mIHRoZSBzYW1lIGdyYXBoLCBidXQgd2l0aG91dCBsb29raW5nIGF0IHRoZSBob3VyIG9mIHRoZSBkYXkifQpnZ3Bsb3QoCiAgZGF0YSA9IG1lbHQoZGF0YV90ZXN0WywgLiguaWQsIGRhdGUsIGdldChpKSwgZGl2ZXR5cGUpXSwKICAgICAgICAgICAgICBpZC52YXJzID0gYygKICAgICAgICAgICAgICAgICIuaWQiLAogICAgICAgICAgICAgICAgImRhdGUiLAogICAgICAgICAgICAgICAgImRpdmV0eXBlIgogICAgICAgICAgICAgICkKICApLAogIGFlcygKICAgIHggPSBhcy5EYXRlKGRhdGUpLAogICAgeSA9IHZhbHVlLAogICAgY29sID0gZGl2ZXR5cGUKICApCikgKwogIGdlb21fcG9pbnQoCiAgICBhbHBoYSA9IDEgLyAxMCwKICAgIHNpemUgPSAuNQogICkgKwogIGZhY2V0X3dyYXAoLiB+IC5pZCwgc2NhbGVzID0gImZyZWUiKSArCiAgc2NhbGVfeF9kYXRlKGRhdGVfbGFiZWxzID0gIiVtLyVZIikgKwogIGxhYnMoeCA9ICJEYXRlIiwgeSA9IGkpICsKICB0aGVtZV9qam8oKSArCiAgdGhlbWUoCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpLAogICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIKICApICsKICBndWlkZXMoY29sb3VyID0gZ3VpZGVfbGVnZW5kKG92ZXJyaWRlLmFlcyA9IGxpc3QoCiAgICBzaXplID0gNywKICAgIGFscGhhID0gMQogICkpKQpgYGAKCkFuZCBpbiBib251cywgd2UgY2FuIGFkZCB0aGUgYmF0aHltZXRyeSB0byB0aGUgM0QgcGxvdC4KCmBgYHtyIGZpZy5jYXA9IlRoaXMgaXMgYXJ0ISJ9Cmh0bWx0b29sczo6dGFnTGlzdChsaXN0KAogIHBsb3RfbHkoKSAlPiUKICBhZGRfdHJhY2UoCiAgICBkYXRhID0gZGF0YV90ZXN0LAogICAgeCA9IH5ob3VyLAogICAgeSA9IH5kYXlfZGVwYXJ0dXJlLAogICAgeiA9IH4gLW1heGRlcHRoLAogICAgY29sb3IgPSB+ZGl2ZXR5cGUsCiAgICBtYXJrZXIgPSBsaXN0KAogICAgICBzaXplID0gMSwKICAgICAgb3BhY2l0eSA9IDAuNQogICAgKSwKICAgIG1vZGUgPSAibWFya2VycyIsCiAgICB0eXBlID0gInNjYXR0ZXIzZCIsCiAgICB0ZXh0ID0gfmRpdmVudW1iZXIKICApICU+JQogIGFkZF90cmFjZSgKICAgIHggPSB+aG91ciwKICAgIHkgPSB+ZGF5X2RlcGFydHVyZSwKICAgIHogPSB+IChsaWdodGF0c3VyZiAvIDIwMCkgKiAyMCwKICAgIGludGVuc2l0eSA9IH4gbGlnaHRhdHN1cmYgLyAyMDAsCiAgICBkYXRhID0gZGF0YVBsb3QsCiAgICB0eXBlID0gIm1lc2gzZCIsCiAgICBzaG93bGVnZW5kID0gRkFMU0UKICApICU+JQogIGFkZF90cmFjZSgKICAgIHggPSB+aG91ciwKICAgIHkgPSB+ZGF5X2RlcGFydHVyZSwKICAgIHogPSB+YmF0aHksCiAgICBkYXRhID0gZGF0YV90ZXN0LAogICAgdHlwZSA9ICJtZXNoM2QiCiAgKSAlPiUKICBsYXlvdXQoCiAgICBzY2VuZSA9IGxpc3QoCiAgICAgIHpheGlzID0gbGlzdCh0aXRsZSA9ICJNYXhpbXVtIGRlcHRoIChtKSIpLAogICAgICB5YXhpcyA9IGxpc3QodGl0bGUgPSAiIyBkYXlzIHNpbmNlIGRlcGFydHVyZSIpLAogICAgICB4YXhpcyA9IGxpc3QodGl0bGUgPSAiSG91ciIpCiAgICApLAogICAgbGVnZW5kID0gbGlzdChpdGVtc2l6aW5nID0gImNvbnN0YW50IikKICApKSkKYGBgCgo+IFdoYXQgYWJvdXQgU291dGhlcm4gRWxlcGhhbnQgU2VhbHMgPyE/CgpUbyBpbnZlc3RpZ2F0ZSB3aHkgaXMgdGhhdCwgbGV0J3MgdHJ5IHNldmVyYWwgcmVwcmVzZW50YXRpb24gb2YgdGhpcyBkYXRhIGZvciB0aGUgaW5kaXZpZHVhbCBgMTQwMDU5YCAoc2VzKS4KCgpgYGB7ciBmaWcuY2FwPSJFdm9sdXRpb24gb2YgdGhlIG1heGltdW0gZGVwdGggcmVhY2hlZCBhY3Jvc3MgdGltZSBmb3IgdGhlIGluZGl2aWR1YWwgMTQwMDU5In0KIyBsZXQncyBwaWNrIGFuIGluZGl2aWR1YWwKZGF0YV90ZXN0IDwtIGRhdGFfY29tcFsuaWQgPT0gImluZF8xNDAwNTkiLF0KCiMgZmlyc3Qgd2UgYXZlcmFnZSBgbGlnaHRhdHN1cmZgIGJ5IGluZGl2aWR1YWxzLCBkYXkgc2luY2UgZGVwYXJ0dXJlIGFuZCBob3VyCmRhdGFQbG90IDwtIGRhdGFfdGVzdFssIC4obGlnaHRhdHN1cmYgPSBtZWRpYW4obGlnaHRhdHN1cmYsIG5hLnJtID0gVCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgcGhhc2UgPSBmaXJzdChwaGFzZSkpLAogICAgICAgICAgICAgICAgICAgICAgYnkgPSAuKC5pZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXlfZGVwYXJ0dXJlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGUgPSBhcy5EYXRlKGRhdGUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhvdXIpXQoKIyB0aGVuIHdlIGNob29zZSB0aGUgdmFyaWFibGUgdG8gcmVwcmVzZW50CmkgPC0gIm1heGRlcHRoIgpnZ3Bsb3QoZGF0YSA9IG1lbHQoZGF0YV90ZXN0WywgLiguaWQsIGRhdGUsIGdldChpKSwgcGhhc2UpXSwKICAgICAgICAgICAgICAgICAgIGlkLnZhcnMgPSBjKCIuaWQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImRhdGUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInBoYXNlIikpLAogICAgICAgYWVzKHggPSBhcy5EYXRlKGRhdGUpLAogICAgICAgICAgIHkgPSB2YWx1ZSwKICAgICAgICAgICBjb2wgPSBwaGFzZSkpICsKICBnZW9tX3BvaW50KGFscGhhID0gMSAvIDUsCiAgICAgICAgICAgICBzaXplID0gLjUpICsKICBmYWNldF93cmFwKC4gfiAuaWQsIHNjYWxlcyA9ICJmcmVlIikgKwogIHNjYWxlX3hfZGF0ZShkYXRlX2xhYmVscyA9ICIlbS8lWSIpICsKICBsYWJzKHggPSAiRGF0ZSIsIHkgPSBpKSArCiAgdGhlbWVfampvKCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpICsKICBndWlkZXMoY29sb3VyID0gZ3VpZGVfbGVnZW5kKG92ZXJyaWRlLmFlcyA9IGxpc3Qoc2l6ZSA9IDcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFscGhhID0gMSkpKQpgYGAKCkZvciB0aGlzIGluZGl2aWR1YWwgd2UgY2FuIHNlZSB0aGF0IHVudGlsIHRoZSBoYWxmIG9mIGl0cyB0cmlwLCB0aGVyZSBpcyBubyBkaXN0aW5jdGlvbiBiZXR3ZWVuIGRheSBhbmQgbmlnaHQgaW4gdGVybXMgb2YgYG1heGRlcHRoYC4gQnV0IEFmdGVyLCBoZSBzdGFydHMgdG8gZGl2ZSBkZWVwZXIgZHVyaW5nIHRoZSBkYXksIGFuZCBzaGFsbG93ZXIgZHVyaW5nIHRoZSBuaWdodC4gQ29udHJhcnkgdG8gdGhlIHByZXZpb3VzIG5lcyBpbmRpdmlkdWFsLCB0aGVyZSBzZWVtcyB0byBiZSBhIGNsZWFyIHBhdHRlcm4uIExldCdzIGxvb2sgYXQgdGhlIGdyYXBoIGluIDNEOgoKYGBge3IgZmlnLmNhcD0iTWF4aW11bSBkZXB0aCBpbiBmdW5jdGlvbiBvZiB0aGUgbnVtYmVyIG9mIGRheXMgc2luY2UgZGVwYXJ0dXJlIGFuZCB0aGUgaG91ciBvZiB0aGUgZGF5IGZvciBpbmRfMTQwMDU5IChzZXMpLiBUaGUgMi1EIHBsYW5lIGFsbG93IHRvIGlkZW50aWZ5IGRheSBhbmQgbmlnaHQgYmFzZWQgb24gdGltZSBhbmQgbG9jYXRpb24uIn0KIyB0aGlzIGlzIGFydCEKaHRtbHRvb2xzOjp0YWdMaXN0KGxpc3QoCiAgcGxvdF9seSgpICU+JQogIGFkZF90cmFjZSgKICAgIGRhdGEgPSBkYXRhX3Rlc3QsCiAgICB4ID0gfmhvdXIsCiAgICB5ID0gfmRheV9kZXBhcnR1cmUsCiAgICB6ID0gfiAtbWF4ZGVwdGgsCiAgICBtYXJrZXIgPSBsaXN0KAogICAgICBzaXplID0gMSwKICAgICAgb3BhY2l0eSA9IDAuOAogICAgKSwKICAgIG1vZGUgPSAibWFya2VycyIsCiAgICB0eXBlID0gInNjYXR0ZXIzZCIsCiAgICB0ZXh0ID0gfmRpdmVudW1iZXIKICApICU+JQogIGFkZF90cmFjZSgKICAgIHggPSB+aG91ciwKICAgIHkgPSB+ZGF5X2RlcGFydHVyZSwKICAgIHogPSB+IChob3VyICogMC4xKSArIDIwLAogICAgaW50ZW5zaXR5ID0gfnBoYXNlX2Jvb2wsCiAgICBkYXRhID0gZGF0YVBsb3RbXVssIHBoYXNlX2Jvb2wgOj0gZmlmZWxzZShwaGFzZSA9PSAibmlnaHQiLCAwLCAxKV1bXSwKICAgIHR5cGUgPSAibWVzaDNkIiwKICAgIHNob3dsZWdlbmQgPSBGQUxTRQogICkgJT4lCiAgbGF5b3V0KAogICAgc2NlbmUgPSBsaXN0KAogICAgICB6YXhpcyA9IGxpc3QodGl0bGUgPSAiTWF4aW11bSBkZXB0aCAobSkiKSwKICAgICAgeWF4aXMgPSBsaXN0KHRpdGxlID0gIiMgZGF5cyBzaW5jZSBkZXBhcnR1cmUiKSwKICAgICAgeGF4aXMgPSBsaXN0KHRpdGxlID0gIkhvdXIiKQogICAgKSwKICAgIGxlZ2VuZCA9IGxpc3QoaXRlbXNpemluZyA9ICJjb25zdGFudCIpCiAgKSkpCmBgYAoKV2UgY2FuIGNsZWFybHkgc2VlIHRoYXQgcGFzcyBoYWxmIG9mIGl0cyB0cmlwLCB0aGlzIGluZGl2aWR1YWwgc3RhcnRzIHRvIGRpdmUgZGVlcGVyIGR1cmluZyB0aGUgZGF5LiBMZXQncyBzZWUgd2hhdCBoYXBwZW4gaWYgd2UgY29sb3IgZGl2ZXMgd2l0aCBgZGl2ZXR5cGVgLgoKYGBge3IgZmlnLmNhcD0iU2FtZSBncmFwaCBidXQgd2l0aCBgbWF4ZGVwdGhgIGNvbG9yZWQgYnkgYGRpdmV0eXBlYCJ9CiMgdGhpcyBpcyBhcnQhCmh0bWx0b29sczo6dGFnTGlzdChsaXN0KAogIHBsb3RfbHkoKSAlPiUKICBhZGRfdHJhY2UoCiAgICBkYXRhID0gZGF0YV90ZXN0LAogICAgeCA9IH5ob3VyLAogICAgeSA9IH5kYXlfZGVwYXJ0dXJlLAogICAgeiA9IH4gLW1heGRlcHRoLAogICAgY29sb3IgPSB+ZGl2ZXR5cGUsCiAgICBtYXJrZXIgPSBsaXN0KAogICAgICBzaXplID0gMSwKICAgICAgb3BhY2l0eSA9IDAuOAogICAgKSwKICAgIG1vZGUgPSAibWFya2VycyIsCiAgICB0eXBlID0gInNjYXR0ZXIzZCIsCiAgICB0ZXh0ID0gfmRpdmVudW1iZXIKICApICU+JQogIGFkZF90cmFjZSgKICAgIHggPSB+aG91ciwKICAgIHkgPSB+ZGF5X2RlcGFydHVyZSwKICAgIHogPSB+IChob3VyICogMC4xKSArIDIwLAogICAgaW50ZW5zaXR5ID0gfnBoYXNlX2Jvb2wsCiAgICBkYXRhID0gZGF0YVBsb3RbXVssIHBoYXNlX2Jvb2wgOj0gZmlmZWxzZShwaGFzZSA9PSAibmlnaHQiLCAwLCAxKV1bXSwKICAgIHR5cGUgPSAibWVzaDNkIiwKICAgIHNob3dsZWdlbmQgPSBGQUxTRQogICkgJT4lCiAgbGF5b3V0KAogICAgc2NlbmUgPSBsaXN0KAogICAgICB6YXhpcyA9IGxpc3QodGl0bGUgPSAiTWF4aW11bSBkZXB0aCAobSkiKSwKICAgICAgeWF4aXMgPSBsaXN0KHRpdGxlID0gIiMgZGF5cyBzaW5jZSBkZXBhcnR1cmUiKSwKICAgICAgeGF4aXMgPSBsaXN0KHRpdGxlID0gIkhvdXIiKQogICAgKSwKICAgIGxlZ2VuZCA9IGxpc3QoaXRlbXNpemluZyA9ICJjb25zdGFudCIpCiAgKQopKQpgYGAKCkl0J3MgaGFyZCB0byB0ZWxsIHNvbWV0aGluZywgbW9zdCBvZiB0aGUgZGl2ZXMgc2VlbSB0byBiZSBmb3JhZ2luZyBkaXZlcywgYW5kIGZvbGxvdyB0aGUgcGF0dGVybiBpZGVudGlmaWVkIHByZXZpb3VzbHkuIFRoZSBvdGhlciBpbnRlcmVzdGluZyByZXN1bHRzIHdvdWxkIGJlIGEgbG90IG9mIGJlbnRoaWMgZGl2ZXMgYXQgdGhlIGJlZ2lubmluZywgYW5kIGRyaWZ0IGRpdmVzIG9jY3VycmluZyBtb3N0bHkgZHVyaW5nIHRoZSBkYXkuIExldCdzIGxvb2sgYXQgYSBzaW1wbGUgMkQgcGxvdDoKCmBgYHtyIGZpZy5jYXA9IktpbmQgb2YgdGhlIHNhbWUgZ3JhcGgsIGJ1dCB3aXRob3V0IGxvb2tpbmcgYXQgdGhlIGhvdXIgb2YgdGhlIGRheSJ9CmdncGxvdCgKICBkYXRhID0gbWVsdChkYXRhX3Rlc3RbLCAuKC5pZCwgZGF0ZSwgZ2V0KGkpLCBkaXZldHlwZSldLAogICAgICAgICAgICAgIGlkLnZhcnMgPSBjKAogICAgICAgICAgICAgICAgIi5pZCIsCiAgICAgICAgICAgICAgICAiZGF0ZSIsCiAgICAgICAgICAgICAgICAiZGl2ZXR5cGUiCiAgICAgICAgICAgICAgKQogICksCiAgYWVzKAogICAgeCA9IGFzLkRhdGUoZGF0ZSksCiAgICB5ID0gdmFsdWUsCiAgICBjb2wgPSBkaXZldHlwZQogICkKKSArCiAgZ2VvbV9wb2ludCgKICAgIGFscGhhID0gMSAvIDUsCiAgICBzaXplID0gLjUKICApICsKICBmYWNldF93cmFwKC4gfiAuaWQsIHNjYWxlcyA9ICJmcmVlIikgKwogIHNjYWxlX3hfZGF0ZShkYXRlX2xhYmVscyA9ICIlbS8lWSIpICsKICBsYWJzKHggPSAiRGF0ZSIsIHkgPSBpKSArCiAgdGhlbWVfampvKCkgKwogIHRoZW1lKAogICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSwKICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iCiAgKSArCiAgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBsaXN0KAogICAgc2l6ZSA9IDcsCiAgICBhbHBoYSA9IDEKICApKSkKYGBgCgpBbmQgaW4gYm9udXMsIHdlIGNhbiBhZGQgdGhlIGJhdGh5bWV0cnkgdG8gdGhlIDNEIHBsb3QuCgpgYGB7ciBmaWcuY2FwPSJUaGlzIGlzIGFydCEifQpodG1sdG9vbHM6OnRhZ0xpc3QobGlzdChwbG90X2x5KCkgJT4lCiAgYWRkX3RyYWNlKAogICAgZGF0YSA9IGRhdGFfdGVzdCwKICAgIHggPSB+aG91ciwKICAgIHkgPSB+ZGF5X2RlcGFydHVyZSwKICAgIHogPSB+IC1tYXhkZXB0aCwKICAgIGNvbG9yID0gfmRpdmV0eXBlLAogICAgbWFya2VyID0gbGlzdCgKICAgICAgc2l6ZSA9IDEsCiAgICAgIG9wYWNpdHkgPSAwLjgKICAgICksCiAgICBtb2RlID0gIm1hcmtlcnMiLAogICAgdHlwZSA9ICJzY2F0dGVyM2QiLAogICAgdGV4dCA9IH5kaXZlbnVtYmVyCiAgKSAlPiUKICBhZGRfdHJhY2UoCiAgICB4ID0gfmhvdXIsCiAgICB5ID0gfmRheV9kZXBhcnR1cmUsCiAgICB6ID0gfiAobGlnaHRhdHN1cmYgLyAyMDApICogMjAsCiAgICBpbnRlbnNpdHkgPSB+IGxpZ2h0YXRzdXJmIC8gMjAwLAogICAgZGF0YSA9IGRhdGFQbG90LAogICAgdHlwZSA9ICJtZXNoM2QiLAogICAgc2hvd2xlZ2VuZCA9IEZBTFNFCiAgKSAlPiUKICBhZGRfdHJhY2UoCiAgICB4ID0gfmhvdXIsCiAgICB5ID0gfmRheV9kZXBhcnR1cmUsCiAgICB6ID0gfmJhdGh5LAogICAgZGF0YSA9IGRhdGFfdGVzdCwKICAgIHR5cGUgPSAibWVzaDNkIgogICkgJT4lCiAgbGF5b3V0KAogICAgc2NlbmUgPSBsaXN0KAogICAgICB6YXhpcyA9IGxpc3QodGl0bGUgPSAiTWF4aW11bSBkZXB0aCAobSkiKSwKICAgICAgeWF4aXMgPSBsaXN0KHRpdGxlID0gIiMgZGF5cyBzaW5jZSBkZXBhcnR1cmUiKSwKICAgICAgeGF4aXMgPSBsaXN0KHRpdGxlID0gIkhvdXIiKQogICAgKSwKICAgIGxlZ2VuZCA9IGxpc3QoaXRlbXNpemluZyA9ICJjb25zdGFudCIpCiAgKSkpCmBgYCAgCg==